package com.carrot.uaa.authorization.response;

import com.carrot.common.core.domain.R;
import com.carrot.uaa.constant.Oauth2Constants;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.GenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.oauth2.core.endpoint.DefaultOAuth2AccessTokenResponseMapConverter;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;

import java.util.Map;

/**
 * 重写认证成功响应格式
 */
public class MyOAuth2AccessTokenResponseHttpMessageConverter extends OAuth2AccessTokenResponseHttpMessageConverter {

    private static final ParameterizedTypeReference<Map<String, Object>> STRING_OBJECT_MAP = new ParameterizedTypeReference<Map<String, Object>>() {
    };
    private GenericHttpMessageConverter<Object> jsonMessageConverter = HttpMessageConverters.getJsonMessageConverter();
    private Converter<OAuth2AccessTokenResponse, Map<String, Object>> accessTokenResponseParametersConverter = new DefaultOAuth2AccessTokenResponseMapConverter();
    @Override
    protected void writeInternal(OAuth2AccessTokenResponse tokenResponse, HttpOutputMessage outputMessage) throws HttpMessageNotWritableException {
        try {
            Map<String, Object> tokenResponseParameters = this.accessTokenResponseParametersConverter
                    .convert(tokenResponse);
            tokenResponseParameters.put(Oauth2Constants.ACCESS_TOKEN_CAM,
                    tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN));
            tokenResponseParameters.remove(OAuth2ParameterNames.ACCESS_TOKEN);
            if (tokenResponseParameters.get(OAuth2ParameterNames.REFRESH_TOKEN) != null) {
                tokenResponseParameters.put(Oauth2Constants.REFRESH_TOKEN_CAM,
                        tokenResponseParameters.get(OAuth2ParameterNames.REFRESH_TOKEN));
                tokenResponseParameters.remove(OAuth2ParameterNames.REFRESH_TOKEN);
            }
            tokenResponseParameters.put(Oauth2Constants.EXPIRES_IN_CAM,
                    tokenResponseParameters.get(OAuth2ParameterNames.EXPIRES_IN));
            tokenResponseParameters.remove(OAuth2ParameterNames.EXPIRES_IN);
            R resultWrapper = R.ok(tokenResponseParameters);
            tokenResponseParameters.put(Oauth2Constants.TOKEN_TYPE_CAM,
                    tokenResponseParameters.get(OAuth2ParameterNames.TOKEN_TYPE));
            tokenResponseParameters.remove(OAuth2ParameterNames.TOKEN_TYPE);
            this.jsonMessageConverter.write(resultWrapper, STRING_OBJECT_MAP.getType(),
                    MediaType.APPLICATION_JSON, outputMessage);
        }
        catch (Exception ex) {
            throw new HttpMessageNotWritableException(
                    "An error occurred writing the OAuth 2.0 Access Token Response: " + ex.getMessage(), ex);
        }
    }
}
